package top.v5it.japi.plus.core.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.AsymmetricAlgorithm;

import java.io.InputStream;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.HashMap;
import java.util.Map;

/**
 * 证书工具
 *
 * @author zhanpu
 * @date 2022/9/29
 */
public class CertUtil {

    private CertUtil() {
        throw new UnsupportedOperationException();
    }

    /**
     * 根据私钥文件读取私钥
     *
     * @param filepath
     * @return
     */
    public static String readPrivateKey(final String filepath) {
        byte[] bytes;
        try {
            bytes = FileUtil.readBytes(filepath);
        } catch (Exception e) {
            throw new IllegalArgumentException(String.format("私钥解析错误，文件路径\"%s\"", filepath), e);
        }
        final PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
        KeyFactory kf;
        try {
            kf = KeyFactory.getInstance(AsymmetricAlgorithm.RSA.getValue());
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalArgumentException("私钥不支持RSA算法");
        }
        byte[] encoded;
        try {
            encoded = kf.generatePrivate(spec).getEncoded();
        } catch (InvalidKeySpecException e) {
            throw new IllegalArgumentException("私钥无效");
        }
        return Base64.encode(encoded);
    }

    /**
     * 根据证书文件获取{@link X509Certificate}
     *
     * @param filepath
     * @return
     */
    public static X509Certificate readX509Certificate(final String filepath) {
        try (InputStream in = FileUtil.getInputStream(filepath)) {
            return (X509Certificate) SecureUtil.readX509Certificate(in);
        } catch (Exception e) {
            throw new IllegalArgumentException("证书[" + filepath + "]解析错误，请检查证书配置是否正确", e);
        }
    }

    /**
     * 根据私钥文件证书基本信息
     *
     * @param filepath
     * @return
     */
    public static Map<String, Object> readX509CertificateForMap(final String filepath) {
        final X509Certificate x509Certificate = readX509Certificate(filepath);
        final String serialNumber = x509Certificate.getSerialNumber().toString();
        final LocalDateTime startTime = LocalDateTime.ofInstant(x509Certificate.getNotBefore().toInstant(), ZoneId.systemDefault());
        final LocalDateTime endTime = LocalDateTime.ofInstant(x509Certificate.getNotAfter().toInstant(), ZoneId.systemDefault());
        final byte[] encoded = x509Certificate.getPublicKey().getEncoded();
        final String publicKey = Base64.encode(encoded);
        final Map<String, Object> objectMap = new HashMap<>();
        objectMap.put("publicKey", publicKey);
        objectMap.put("serialNo", serialNumber);
        objectMap.put("startTime", startTime);
        objectMap.put("endTime", endTime);
        return objectMap;
    }
}
